/*
用途项目：自定义滚动条实现
*/
(function (win, doc, $) {
    // 定义的滚动条的构造函数
    function CusScrollBar(options) {
        // 函数的调用
        this._init(options);
    }

    // 对象的合并
    $.extend(CusScrollBar.prototype, {
        _init: function (options) {
            // 闭包
            var self = this;
            // 初始化参数
            self.options = {
                scrollDir: 'Y',       //滚动的方向
                contentSelector: '',  //滚动内容区选择器
                barSelector: '',      //滚动条选择器
                sliderSelector: '',   //滚动滑块选择器
                wheelStep: 100,        //滚动步长（鼠标移动一下，内容滚动的幅度）
            }
            // 覆盖参数
            $.extend(true, self.options, options || {});
            self._initDomEvent();
            return self;
        },

        /**
         * 初始化DOM引用
         * @method _initDomEvent
         * @return {CusScrollBar}
         */
        _initDomEvent: function () {
            var opts = this.options;
            // 滚动内容区对象，必填项
            this.$cont = $(opts.contentSelector);
            // 滚动条滑块对象，必须项
            this.$slider = $(opts.sliderSelector);
            // 滚动条对象
            this.$bar = opts.barSelector ? $(opts.barSelector) : self.$slider.parent();
            // 获取文档对象
            this.$doc = $(doc);
            // 获取初始化滑块拖动功能
            this._initSliderDragEvent();
            // 获取同步滑块的位置
            this._bindContentScroll();
            // 获取鼠标滚轮事件
            this._bindMousewheel();
            // 获取内容来定义滑块的高度
            this._initSliderHeight();

        },
        // 根据内容来定义滑块的高度
        _initSliderHeight: function () {
            // console.log(this.$cont[0].scrollHeight)
            var rate = this.$cont.innerHeight() / this.$cont[0].scrollHeight;
            // console.log('123456',rate);
            if (rate < 1) {
                var sliderHeight = rate * this.$bar.height();
                this.$slider.css('height', sliderHeight);
            } else {
                this.$bar.css('display', 'none');
            }
        },


        /**
         * 初始化滑块拖动功能
         * @return {[Object]} [this]
         */
        _initSliderDragEvent: function () {
            var self = this;
            // 滑块元素
            var slider = this.$slider,
                sliderEl = slider[0];
            // 如果元素存在
            if (sliderEl) {
                var doc = this.$doc,
                    dragStartPagePostion,
                    dragStartScrollPostion,
                    dragContBarRate;

                function mousemoveHandler(e) {
                    e.preventDefault();
                    if (dragStartPagePostion == null) {
                        return;
                    }
                    //内容开始卷曲的高度+rate*(鼠标释放的位置-开始的位置) == 就是内容滑动的位置
                    self.scrollTo(dragStartScrollPostion + (e.pageY - dragStartPagePostion) * dragContBarRate);
                }

                slider.on('mousedown', function (e) {
                    e.preventDefault();
                    // 获取鼠标的点击的开始位置
                    dragStartPagePostion = e.pageY;
                    // 获取内容区域的向上卷区的高度
                    dragStartScrollPostion = self.$cont[0].scrollTop;
                    dragContBarRate = self.getMaxScrollPosition() / self.getMaxSliderPosition();
                    // 监听的document对象
                    doc.on('mousemove.scroll', mousemoveHandler).on('mouseup.scroll', function () {
                        doc.off('.scroll');
                    });
                });
                return self;
            }
        },

        // 计算滑块的当前位置
        getSliderPosition: function () {
            var self = this,
                // 滑块可以移动的距离
                maxSliderPosition = self.getMaxSliderPosition();
            // 滑块移动的距离
            return Math.min(maxSliderPosition, maxSliderPosition * self.$cont[0].scrollTop / self.getMaxScrollPosition());
        },

        // 内容可滚动的高度
        getMaxScrollPosition: function () {
            var self = this;
            return Math.max(self.$cont.innerHeight(), self.$cont[0].scrollHeight) - self.$cont.innerHeight();

        },

        //滑块可移动的距离
        getMaxSliderPosition: function () {
            var self = this;
            return self.$bar.height() - self.$slider.height();
        },

        // 监听内容的滚动，同步滑块的位置
        _bindContentScroll: function () {
            var self = this;
            self.$cont.on('scroll', function () {
                var sliderEl = self.$slider && self.$slider[0];
                if (sliderEl) {
                    // 设置滑块的位置
                    sliderEl.style.top = self.getSliderPosition() + 'px';
                }
            });
            return self;
        },

        // 鼠标滚轮事件
        _bindMousewheel: function () {
            var self = this;
            // on监听事件，多个事件利用空格分开
            self.$cont.on('mousewheel DOMMouseScroll', function (e) {
                //console.log(self.getMaxScrollPosition(), self.getMaxSliderPosition(), self.getSliderPosition());

                // 判断原生事件对象的属性
                var oEv = e.originalEvent,
                    //原生事件对象,（其他浏览器负数向下，firefox正数向下,所以在wheelDelta前面有负数）
                    // 想要达到的效果，鼠标向下滚动，内容向下走
                    wheelRange = oEv.wheelDelta ? -oEv.wheelDelta / 120 : (oEv.detail || 0) / 3;
                // 调用scrollTo方法。

                if(wheelRange>0){
                    if(self.getMaxScrollPosition()!==0&&self.getMaxSliderPosition()!==self.getSliderPosition()){
                        e.preventDefault();
                    }
                }else{
                    if(self.getMaxScrollPosition()!==0&&self.getSliderPosition()!==0){
                        e.preventDefault();
                    }
                }

                self.scrollTo(self.$cont[0].scrollTop + wheelRange * self.options.wheelStep);
            });
        },

        // 内容的滑动
        scrollTo: function (positonVal) {
            var self = this;
            self.$cont.scrollTop(positonVal);
        }
    });

    win.CusScrollBar = CusScrollBar;
})(window, document, jQuery)